/**
 * @desc 函数防抖 
 * 当事件触发时，相应的函数并不会立即触发，而是会等待一定的时间；
 * 当事件密集触发时，函数的触发会被频繁的推迟；
 * 只有等待了一段时间也没有事件触发，才会真正的执行响应函数。
 
 * @example 适用场景：
 *  频繁的点击按钮，触发某个事件
 *  输入框中频繁的输入内容
 
 * @param  {func} Function 要防抖的函数。
 * @param  {delay} number 需要延迟的毫秒数。
 * @param  {immediate} boolean 是否立即执行。
 * @return {Function} 新的防抖函数。
 */

function debounce(fn, delay = 200, immediate = false) {
	// 1.定义一个定时器, 保存上一次的定时器
	let timer = null
	let isInvoke = false    // 是否激活了立即执行
	// 2.真正执行的函数
	const _debounce = function(...args) {
		// 取消上一次的定时器
		if (timer) clearTimeout(timer)
		// 判断是否需要立即执行
		if (immediate && !isInvoke) {
			fn.apply(this, args)
			isInvoke = true // 已经立即执行, 阻止下次触发的立即执行
		} else {
			// 延迟执行
			timer = setTimeout(() => {
				// 外部传入的真正要执行的函数
				fn.apply(this, args)
				isInvoke = false // 将isInvoke初始化
			}, delay)
		}
	}
	// 封装取消功能
	_debounce.cancel = function() {
		if (timer) clearTimeout(timer)
		timer = null
		isInvoke = false
	}
	return _debounce
}

export { debounce };